//
//  3DObjFile.c
//  
//
//  Created by David Michaeli on 26/08/12.
//
//

#include "3DObjFile.h"
#include "BufferedFile.h"
#include <stdlib.h>
#include <stdio.h>
#include <memory.h>
#include <ctype.h>


//================================================
void ObjFreeModel(ObjModel* model)
{
    free(model->NormalArray);
    free(model->TexCoordArray);
    free(model->TriangleArray);
    free(model->VertexArray);
    free(model);
}

//================================================
ObjModel* ObjLoadFile(char* szFileName)
{
    int nV = 0, nN = 0, nT = 0, nF = 0;
    char line[256] = {0};
    ObjModel* ret = (ObjModel*) calloc(1, sizeof(ObjModel));
    char *tok = NULL;
    char *tok1 = NULL;
    BufferedFile *file = NULL;
    
    memset(ret, 0, sizeof(ObjModel));
    
    // Open the file in order to collect statistics
    file = OpenFile(szFileName, "r");
    if (file==NULL)
    {
        return NULL;
    }
    
	while (ReadLineFromFile(file, line, 255))
	{
        tok = line;
        
        // eliminate spaces
        while (isspace(*tok))
        {
            tok++;
        }
        
        if (tok[0]=='v' && tok[1]=='n') ret->nNormal++;
        else if (tok[0]=='v' && tok[1]=='t') ret->nTexCoord++;
        else if (tok[0]=='v') ret->nVertex++;
        else if (tok[0]=='f') ret->nTriangle++;
    }
    
    CloseFile(file);
    
    // allocate memory
    ret->VertexArray   = (ObjVertex*)   malloc(sizeof(ObjVertex) * ret->nVertex);
    ret->NormalArray   = (ObjNormal*)   malloc(sizeof(ObjNormal) * ret->nNormal);
    ret->TexCoordArray = (ObjTexCoord*) malloc(sizeof(ObjTexCoord) * ret->nTexCoord);
    ret->TriangleArray = (ObjTriangle*) malloc(sizeof(ObjTriangle) * ret->nTriangle);
	
    // Open the file again in order to actually parse it
    file = OpenFile(szFileName, "r");
    if (file==NULL)
    {
        // free everything
        ObjFreeModel(ret);
        return NULL;
    }
    
	while (ReadLineFromFile(file, line, 255))
	{
        tok1 = line;
        
        // eliminate spaces
        while (isspace(*tok1))
        {
            tok1++;
        }
        
        // Normals
        if (tok1[0]=='v' && tok1[1]=='n')
        {
            sscanf(line, "vn %f %f %f",
                   &ret->NormalArray[nN].x,
                   &ret->NormalArray[nN].y,
                   &ret->NormalArray[nN].z);
            nN++;
        }
        // Texture mapping coordinates
        else if (tok1[0]=='v' && tok1[1]=='t')
        {
            sscanf(line, "vt %f %f",
                   &ret->TexCoordArray[nT].u,
                   &ret->TexCoordArray[nT].v);
            nT++;
        }
        // Vertices
        else if (tok1[0]=='v')
        {
            sscanf(line, "v %f %f %f",
                   &ret->VertexArray[nV].x,
                   &ret->VertexArray[nV].y,
                   &ret->VertexArray[nV].z);
            nV++;
        }
        // Faces
        else if (tok1[0]=='f')
        {
            int i = 0;
            tok = strtok (line, " \t\n");
            
            for (i=0; i<3; i++)
            {
                tok = strtok (NULL, " \t\n");
                ret->TriangleArray[nF].Vertex[i] = atoi(tok);
                
                while (*tok != '\0' && *tok != '/')
                {
                    tok++;
                }
                
                if ( *tok == '\0' )
                {
                    ret->TriangleArray[nF].TexCoord[i] = 0;
                    ret->TriangleArray[nF].Normal[i] = 0;
                    continue;
                }
                
                else if (*tok == '/')
                {
                    ret->TriangleArray[nF].TexCoord[i] = atoi(++tok);
                }
                
                while (*tok != '\0' && *tok != '/')
                {
                    tok++;
                }
                
                if ( *tok == '\0' )
                {
                    ret->TriangleArray[nF].Normal[i] = 0;
                    continue;
                }
                
                else if (*tok == '/')
                {
                    ret->TriangleArray[nF].Normal[i] = atoi(++tok);
                }
                
            }

            nF++;
        }
    }
    
    CloseFile(file);
    
    return ret;

}

//================================================
int ObjSaveFile(ObjModel* model, char* fname)
{
    
    return 0;
}

